﻿using System;
using System.Data;
using System.Globalization;
using System.Runtime.Serialization;

using PublicDomain.Data.Csv.Properties;

namespace PublicDomain.Data.Csv.Metadata
{
    [DataContract(Namespace = "www.publicdomain.net\\data\\csv\\metadata\\2013-11-26\\", Name = "CsvColumnDefinition")]
    public class CsvColumnDefinition
    {
        [DataMember(Name = "ColumnName", IsRequired = true)]
        public string ColumnName { get; set; }

        [DataMember(Name = "ColumnOrdinal", IsRequired = true)]
        public int ColumnOrdinal { get; set; }

        [DataMember(Name = "DataType", IsRequired = true)]
        public DbType DataType { get; set; }

        [DataMember(Name = "ColumnSize", IsRequired = true)]
        public int ColumnSize { get; set; }

        public object Tag { get; set; }

        public Type FieldType
        {
            get
            {
                return DbTypeToType(this.DataType);
            }
        }

        public static Type DbTypeToType(DbType columnDbType)
        {
            switch (columnDbType)
            {
                case DbType.AnsiString:
                    return typeof(string);

                case DbType.AnsiStringFixedLength:
                    return typeof(string);

                case DbType.Binary:
                    return typeof(string);

                case DbType.Boolean:
                    return typeof(bool);

                case DbType.Byte:
                    return typeof(byte);

                case DbType.Currency:
                    return typeof(decimal);

                case DbType.Date:
                    return typeof(DateTime);

                case DbType.DateTime:
                    return typeof(DateTime);

                case DbType.DateTime2:
                    return typeof(DateTime);

                case DbType.DateTimeOffset:
                    return typeof(DateTimeOffset);

                case DbType.Decimal:
                    return typeof(decimal);

                case DbType.Double:
                    return typeof(double);

                case DbType.Guid:
                    return typeof(Guid);

                case DbType.Int16:
                    return typeof(Int16);

                case DbType.Int32:
                    return typeof(Int32);

                case DbType.Int64:
                    return typeof(Int64);

                case DbType.Object:
                    return typeof(string);

                case DbType.SByte:
                    return typeof(sbyte);

                case DbType.Single:
                    return typeof(Single);

                case DbType.String:
                    return typeof(string);

                case DbType.StringFixedLength:
                    return typeof(string);

                case DbType.Time:
                    return typeof(TimeSpan);

                case DbType.UInt16:
                    return typeof(UInt16);

                case DbType.UInt32:
                    return typeof(UInt32);

                case DbType.UInt64:
                    return typeof(UInt64);

                case DbType.VarNumeric:
                    return typeof(decimal);

                case DbType.Xml:
                    return typeof(string);

                default:
                    throw new CsvDataInvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.DbTypeMappingError, columnDbType));
            }
        }

        public override string ToString()
        {
            var result = String.Format(
                CultureInfo.CurrentCulture,
                Resources.CsvColumnSchemaToStringFormatString, 
                this.ColumnName, 
                this.ColumnOrdinal,
                this.DataType);

            return result;
        }
    }
}
